#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/3/10 11:28
# @Author  : liutianwei
# @File    : DockerIntegrated.py
# @Software: PyCharm
import os
import signal
import subprocess
import sys
import threading
import time


class MangoDocker:
    def __init__(self, image, workspace):
        self.__images = image
        self.__workspace = workspace
        self.__docker_cmd = [
            "docker", "run", "-dit",
            "--user", f"{os.getuid()}:{os.getgid()}",
            "-w", self.__workspace
        ]
        self.__volumes = [
            "-v", "/etc/passwd:/etc/passwd:ro",
            "-v", "/etc/group:/etc/group:ro",
            self.__images,
            "bash"
        ]
        self.__container_id = ""

    def mount(self, *args):
        for param in args:
            self.__docker_cmd.append('-v')
            self.__docker_cmd.append(param)
        self.__docker_cmd = self.__docker_cmd + self.__volumes

    def start(self):
        """ 启动 Docker 并运行 pytest """
        print(self.__docker_cmd)
        try:
            # 启动 Docker 容器
            self.__container_id = subprocess.check_output(self.__docker_cmd, universal_newlines=True).strip()
            return 0
        except subprocess.CalledProcessError as e:
            print(f"Docker 启动失败: {e.stderr}")
            return -1

    def excute(self, command):
        print(f"pytest is all ready, container_id: {self.__container_id}")

        docker_exec_cmd = ["docker", "exec", "-i", self.__container_id, "bash", "-c", command]
        try:
            proc = subprocess.Popen(docker_exec_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                    universal_newlines=True, bufsize=1)

            last_output_time = time.time()

            # **后台线程监控超时**
            def monitor_timeout():
                while proc.poll() is None:
                    if time.time() - last_output_time > 60:
                        print("pytest30秒无输出，强制终止...")
                        proc.kill()
                        proc.wait()
                        self.free()
                        return
                    time.sleep(5)

            threading.Thread(target=monitor_timeout, daemon=True).start()

            for line in iter(proc.stdout.readline, ''):
                print(line, end='')
                sys.stdout.flush()
                last_output_time = time.time()

            proc.wait()
            return proc.returncode

        except KeyboardInterrupt:
            self.free()
            return -1

    def free(self):
        """ 关闭并删除 Docker 容器 """
        print(f"用户中断，正在清理 Docker 容器 {self.__container_id}...")
        result = subprocess.run(["docker", "ps", "-q", "-f", f"id={self.__container_id}"], stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        if bool(result.stdout.strip()):
            try:
                stop_result = subprocess.check_call(["docker", "stop", self.__container_id])
            except subprocess.CalledProcessError as e:
                print(f"停止docker容器{self.__container_id}失败, 状态码：{e}")
            try:
                rm_result = subprocess.check_call(["docker", "rm", self.__container_id])
            except subprocess.CalledProcessError as f:
                print(f"停止docker删除{self.__container_id}失败, 状态码：{f}")
        else:
            print(f"{self.__container_id} is not exist")
        return 0
